using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace OpenPanekitEditor
{
    public class CameraControl
    {
        public enum Mode{
            RotationAndDistance
        }
        public Mode CalcMode;
        public Vector3 CameraPosition = new Vector3(0f, 10f, -50f);
        public Vector3 CameraReferencePosition=new Vector3(0f,0f,0f);
        public float CameraAngleYaw=0f;
        public float CameraAnglePitch=1f;
        public float CameraDitance=10f;
        public Vector3 CameraUp = new Vector3(0f, 1f, 0f);
        public float ScreenWidth;
        public float ScreenHeight;
        public float Znear = 0.2f;
        public float Zfar = 1000f;
        public float MouseSence = 4f;
        public delegate Vector3 GetReferncePosionDelegate();
        GetReferncePosionDelegate get_refpoint=null;

        public Matrix GetVewingMatrix()
        {
            switch (CalcMode)
            {
                case Mode.RotationAndDistance:
                    return GetViewMatrix_RotationAndDistance();
                default:
                    return Matrix.Identity;
            }
        }
        public Matrix GetProjectionMatrix()
        {
            return Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, ScreenWidth / ScreenHeight, Znear, Zfar);
        }
        public Viewport GetViewPort()
        {
            Viewport v = new Viewport();
            v.Width = (int)ScreenWidth;
            v.Height = (int)ScreenHeight;
            v.X = v.Y = 0;
            v.MaxZ = Zfar;
            v.MinZ = Znear;
            return v;
        }
        private Matrix GetViewMatrix_RotationAndDistance()
        {
            Matrix mh = new Matrix();
            Vector3 zv = new Vector3(0f, 0f, - CameraDitance);
            if (get_refpoint != null)
            {
                CameraReferencePosition = get_refpoint();
            }
            mh.RotateYawPitchRoll(CameraAngleYaw, CameraAnglePitch, 0f);
            CameraPosition = Vector3.TransformCoordinate(zv, mh);
            CameraPosition += CameraReferencePosition;
            return Matrix.LookAtLH(CameraPosition, CameraReferencePosition, CameraUp);
        }

        int mlast_x, mlast_y;
        public void MouseDown(int x, int y)
        {
            mlast_x = x;
            mlast_y = y;
        }
        public void MouseMove(int x, int y)
        {
            CameraAngleYaw += (float)(x - mlast_x) * (1f / ScreenWidth) * MouseSence;
            CameraAnglePitch += (float)(y - mlast_y) * (1f / ScreenHeight) * MouseSence;
            if (CameraAnglePitch > (float)Math.PI / 2f)
            {
                CameraAnglePitch = (float)Math.PI / 2f - 0.01f;
            }
            if (CameraAnglePitch < -(float)Math.PI / 2f)
            {
                CameraAnglePitch = -(float)Math.PI / 2f + 0.01f;
            }
            mlast_x = x;
            mlast_y = y;
        }
        public void MouseWheel(int d)
        {
            CameraDitance += d / 50f;
            if (CameraDitance < 2f)
                CameraDitance = 2f;
        }
        public void SetReferncePosionMethod(GetReferncePosionDelegate method)
        {
            get_refpoint = method;
        }
    }
}
